using System;
using System.Collections.Generic;
using System.Text;
using ACS.Compiler.Tables;
using ACS.Compiler.Tables.Modes;
using ACS.Compiler.Util;
using ACS.Compiler.Synthes;
using ACS.Compiler.Tree.Interfaces;

namespace ACS.Compiler.Tree.Impl
{
    public class Return : Statement
    {
        private IExpression _value;

        public override void MatchSelect(Select select)
        {
            MatchExpression(select);
        }

        public override void MatchExpression(IExpression expression)
        {
            _value = expression;
        }

        public override void MatchCall(Call call)
        {
            MatchExpression(call);
        }

        public override void MatchIdent(Ident ident)
        {
            MatchExpression(ident);
        }

        public override Statements StatementType
        {
            get { return Statements.Return; }
        }

        public IExpression Value
        {
            get { return _value; }
        }

        public override void Resolve(string ns, DataTable localData)
        {
            Mode procRetMode = null;
            if (Parser.Parser.CurrentProcedure !=null)
            {
                procRetMode = Parser.Parser.CurrentProcedure.RetMode;
            } 
            if (_value != null && procRetMode != null)
            {
                Mode retMode = _value.ModeResolveExpression(ns, localData, null);
                if (!ModesTable.Castable(procRetMode, retMode))
                {
                    Logger.Instance.TraceModesNotEquals(procRetMode, retMode, this);
                }
                return;
            } else
            {
                if (_value != null)
                {
                    Logger.Instance.TraceError("Can't return value from this context", this);
                } else
                {
                    if (procRetMode != null)
                    {
                        Logger.Instance.TraceError("Return value not defined", this);
                    }
                }
            }
        }

        public override void Format()
        {
            if (_value == null)
            {
                Formatter.Current.Format("return;");
            }
            else
            {
                Formatter.Current.Format("return " + Value.ToDeclareString() + ";");
            }
        }
    }
}
